#include "tabooList.h"
#include "main-tools.h"
#include <stdio.h>
#include <stdlib.h>

PtabooList initTabooList(int* _N, TabooExpire now){
	PtabooList result = (PtabooList)malloc(sizeof(TabooList));
	checkMalloc(result, "tabooList:initTabooList:1");
	result->N = _N;
	result->tm = (TabooMat)malloc(*_N*sizeof(PtabooExpire));
	checkMalloc(result->tm, "tabooList:initTabooList:2");
	int i,j;
	for (i=0; i<*_N; i++){
		result->tm[i] = (PtabooExpire)malloc(*_N*sizeof(TabooExpire));
		checkMalloc(result->tm[i], "tabooList.c:initTabooList:3");
		for(j=0;j<i;j++)
			result->tm[i][j] = now;
	}
	return result;
}

//TODO testing
void freeTabooList(PtabooList ptl){
	free(ptl->tm);
	free(ptl);
}

//TODO testing
void resetTabooList(PtabooList ptl,TabooExpire resetvalue){
	int i;
	int j;
	for (i=0;i<*ptl->N;i++){
		for (j=(i+1);j<*ptl->N;j++){
			ptl->tm[i][j]=resetvalue;
		}
	}
}

PtabooExpire getTabooExpireInList(PtabooList ptl, PedgeID pid) {
	validateEdgeID(pid);
	return &ptl->tm[pid->i][pid->j];
}

//TODO si potrebbe mettere come precondizione il fatto che l'arco sia gia' stato validato? anche perche' in documentazione c'e' gia'!
void setTaboo(PtabooList ptl, PedgeID pid, int tenure, TabooExpire now){
	validateEdgeID(pid);
	ptl->tm[pid->i][pid->j] = (TabooExpire)(now + tenure);
}

bool isEdgeTaboo(PtabooList ptl, PedgeID pid, TabooExpire now){
	return isTaboo(getTabooExpireInList(ptl, pid), now);
}

int getEdgeTenure(PtabooList ptl, PedgeID pid, TabooExpire now){
	return getTenure(getTabooExpireInList(ptl, pid), now);
}

void printTabooList(FILE* f, PtabooList ptl){
	int i, j;
	printf("grandezza tabooList: %d\n", *ptl->N);
	fprintf(f, "i\\j|");
	for (i=0; i<*ptl->N; i++){
		fprintf(f, "%3d|", (i+1));
	}
	fprintf(f,"\n");
	for (i=0; i<*ptl->N; i++){
		fprintf(f, "%3d|", i+1);
		for (j=0; j<=i; j++){
			fprintf(f, "---|");
		}
		for (j=(i+1); j<*ptl->N; j++){
			fprintf(f,"%3lu",ptl->tm[i][j]);
			fprintf(f, "|");
		}
		fprintf(f, "\n");
	}
}

void printTabooListExpirations(FILE* f, PtabooList ptl, TabooExpire now, int k){
	int i,j;
	fprintf(f, "Matrice TabooList per veicolo %d: expirations. now e' %lu\ni\\f|", k+1, now);
	for(i=0; i<*ptl->N; i++) //prints row header
		fprintf(f, "%3d|",i+1);
	fprintf(f, "\n");
	for(i=0; i<*ptl->N; i++){ //prints rows
		fprintf(f, "%3d|",i+1);
		for(j=0; j<i+1; j++)
			fprintf(f, "---|");
		for(j=i+1; j<*(ptl->N); j++)
			fprintf(f, "%3lu|", ptl->tm[i][j]);
		fprintf(f, "\n");
	}
}

void printTabooListTenures(FILE* f, PtabooList ptl, TabooExpire now, int k) {
	int i,j;
	fprintf(f, "Matrice TabooList per veicolo %d: tenures.\ni\\f|", k+1);
	for(i=0; i<*ptl->N; i++) //prints row header
		fprintf(f, "%3d|",i+1);
	fprintf(f, "\n");
	for(i=0; i<*ptl->N; i++){ //prints rows
		fprintf(f, "%3d|",i+1);
		for(j=0; j<i+1; j++)
			fprintf(f, "---|");
		for(j=i+1; j<*(ptl->N); j++)
			fprintf(f, "%3d|", getTenure(&(ptl->tm[i][j]), now));
		fprintf(f, "\n");
	}
}

void printTabooListAsSet(FILE* f, PtabooList ptl, TabooExpire now, int k) {
	int i,j;
	PedgeID temp;
	fprintf(f, "\nTabooList %d-esima vigente al termine dell'iterazione %lu [tenure mancanti]\n {", k+1, now);
	for(i=0; i<*ptl->N; i++){ //prints rows
		for(j=i+1; j<*(ptl->N); j++) {
			temp = initEdgeID(i, j);
			if(isEdgeTaboo(ptl, temp, now)) {
				printEdgeID(f, temp);
				fprintf(f, "[:%d]\t", getEdgeTenure(ptl, temp, now));
			}
		}
	}
	fprintf(f, "}\n\n");
}
